package de.axa.smartfix.monitoring.model.provider;

import java.beans.PropertyChangeEvent;
import java.util.Observable;
import java.util.Observer;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;

import de.axa.smartfix.monitoring.model.IMonitor;
import de.axa.smartfix.monitoring.model.MonitorManager;

public class TreeMonitorContentProvider implements Observer,
		ITreeContentProvider {

	private TreeViewer viewer;

	public Object[] getChildren(Object parentElement) {
		if (parentElement instanceof IMonitor)
			return ((IMonitor) parentElement).getChildren();

		return null;
	}

	public Object getParent(Object element) {
		if (element instanceof IMonitor)
			return ((IMonitor) element).getParent();

		return null;
	}

	public boolean hasChildren(Object element) {
		if (element instanceof IMonitor)
			return ((IMonitor) element).getChildren().length > 0;

		return false;
	}

	public Object[] getElements(Object inputElement) {
		if (inputElement instanceof MonitorManager) {
			MonitorManager m = (MonitorManager) inputElement;
			return m.toArray();
		}
		return null;
	}

	public void dispose() {
		// TODO Auto-generated method stub

	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.viewer = (TreeViewer) viewer;

		if (oldInput != null)
			removeListener(oldInput);
		else if (newInput != null)
			addListener(newInput);
	}

	private void removeListener(Object oldInput) {
		IMonitor[] children = new IMonitor[0];
		
		if (oldInput instanceof Observable) {
			((Observable) oldInput).deleteObserver(this);
		}		
		if (oldInput instanceof MonitorManager) {
			MonitorManager manager = (MonitorManager) oldInput;
			children = manager.toArray();
		} else if (oldInput instanceof IMonitor) {
			IMonitor monitor = (IMonitor) oldInput;
			children = monitor.getChildren();
		}

		for (IMonitor child : children) {
			removeListener(child);
		}
	}

	private void addListener(Object oldInput) {
		IMonitor[] children = new IMonitor[0];
		
		if (oldInput instanceof Observable) {
			((Observable) oldInput).addObserver(this);
		}

		if (oldInput instanceof MonitorManager) {
			MonitorManager manager = (MonitorManager) oldInput;
			children = manager.toArray();
		} else if (oldInput instanceof IMonitor) {
			IMonitor monitor = (IMonitor) oldInput;
			children = monitor.getChildren();
		}

		for (IMonitor child : children) {
			addListener(child);
		}
	}

	public void update(Observable o, Object arg) {
		if (viewer == null || viewer.getTree().isDisposed())
			return;
		
		if (arg instanceof PropertyChangeEvent) {
			PropertyChangeEvent event = (PropertyChangeEvent) arg;
			final String name = event.getPropertyName();
			
			if (event.getOldValue().equals(event.getNewValue()))
				return;
			
			if (name.equals(IMonitor.PROPERTY_COUNT) ||
				name.equals(IMonitor.PROPERTY_NAME) ||
				name.equals(IMonitor.PROPERTY_OLDEST)) {
				viewer.update(event.getSource(), new String[] {event.getPropertyName()});
			} else if (name.equals(IMonitor.PROPERTY_PARENT)) {
				if (event.getOldValue() != null) {
					viewer.remove(event.getOldValue(), new Object[]{event.getSource()});
				}
				if (event.getNewValue() != null) {
					viewer.add(event.getNewValue(), event.getSource());
				}
			}
		}
	}

}
